package com.imy.virtual.client.hook.proxies.atm;

import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.util.TypedValue;

import com.imy.virtual.client.core.VirtualCore;
import com.imy.virtual.client.hook.base.MethodProxy;
import com.imy.virtual.client.ipc.ActivityClientRecord;
import com.imy.virtual.client.ipc.VActivityManager;
import com.imy.virtual.helper.compat.ActivityManagerCompat;
import com.imy.virtual.helper.utils.ArrayUtils;
import com.imy.virtual.helper.utils.ComponentUtils;
import com.imy.virtual.helper.utils.VLog;
import com.imy.virtual.os.VUserHandle;


import java.lang.reflect.Method;

public class MethodProxies {

  private static final String TAG = "ATM";

  static class StartActivity extends MethodProxy {

    @Override
    public String getMethodName() {
      return "startActivity";
    }

    @Override
    public Object call(Object who, Method method, Object... args) throws Throwable {
      VLog.i( " ATM  ---->StartActivity 类 " + who + "   " + method.getName() + "    参数长度" + args.length);

      int intentIndex = ArrayUtils.indexOfObject(args, Intent.class, 1);
      if (intentIndex < 0) {
        return ActivityManagerCompat.START_INTENT_NOT_RESOLVED;
      }

      int resultToIndex = ArrayUtils.indexOfObject(args, IBinder.class, 2);
      String resolvedType = (String) args[intentIndex + 1];
      Intent intent = (Intent) args[intentIndex];
      intent.setDataAndType(intent.getData(), resolvedType);
      //token
      IBinder resultTo = resultToIndex >= 0 ? (IBinder) args[resultToIndex] : null;
      int userId = VUserHandle.myUserId();
      if (ComponentUtils.isStubComponent(intent)) {
        VLog.i(TAG, " ATM MethodProxies StartActivity 启动 intent :" + intent);
        return method.invoke(who, args);
      }
      String resultWho = null;
      int requestCode = 0;
      Bundle options = ArrayUtils.getFirst(args, Bundle.class);
      if (resultTo != null) {
        resultWho = (String) args[resultToIndex + 1];
        requestCode = (int) args[resultToIndex + 2];
      }
      args[intentIndex - 1] = getHostPkg(); //增加包名 该参数关键 内部会进行包名的一些校验操作不传会引发错误
      ActivityInfo activityInfo = VirtualCore.get().resolveActivityInfo(intent, userId);
      Log.i(TAG, "activityInfo:" + activityInfo);
      //解析 ActivityInfo
      if (activityInfo == null) {
        VLog.e(TAG, "VActivityManager", "Unable to resolve activityInfo : " + intent);
        if (intent.getPackage() != null && isAppPkg(intent.getPackage())) {
          return ActivityManagerCompat.START_INTENT_NOT_RESOLVED;
        }
        return method.invoke(who, args);
      }

      //获取下activity的状态
      VActivityManager.get().getService().logActivity();
      // 调用远程 VAMS.startActivity
      int res = VActivityManager.get().startActivity(intent, activityInfo, resultTo, options, resultWho, requestCode, VUserHandle.myUserId());
      Log.i(TAG, "res:" + res);
      if (res != 0 && resultTo != null && requestCode > 0) {
        VActivityManager.get().sendActivityResult(resultTo, resultWho, requestCode);
      }
      // 处理 Activity 切换动画，因为此时动画还是 Host 的 Stub Activity 默认动画，需要覆盖成子程序包的动画
      if (resultTo != null) {
        ActivityClientRecord r = VActivityManager.get().getActivityRecord(resultTo);
        if (r != null && r.activity != null) {
          try {
            TypedValue out = new TypedValue();
            Resources.Theme theme = r.activity.getResources().newTheme();
            theme.applyStyle(activityInfo.getThemeResource(), true);
            if (theme.resolveAttribute(android.R.attr.windowAnimationStyle, out, true)) {

              TypedArray array = theme.obtainStyledAttributes(out.data,
                  new int[] {
                      android.R.attr.activityOpenEnterAnimation,
                      android.R.attr.activityOpenExitAnimation
                  });

              r.activity.overridePendingTransition(array.getResourceId(0, 0), array.getResourceId(1, 0));
              array.recycle();
            }
          } catch (Throwable e) {
            // Ignore
          }
        }
      }
      return res;
    }
  }
}
